#!/usr/bin/python
#
# Copyright (c) 2020 NVI, Inc.
#
# This file is part of VLBI Field System
# (see http://github.com/nvi-inc/fs).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""application that starts a thread that receives the output from 'tail -f'. """

from Tkinter import *
import sys
import time
import threading
import os
import popen2


class MainGui:
	"""MainGui makes graphic stuf...
	"""
	filename = ''
	pid = 0
	
	def __init__(self, title = 'Logreader'):


		global master
		#make Tk object:
		master = Tk()

		#make tools, make it global so object has the same reference to all classes
		global tools
		tools = Tools()
		master.title(title)

		master.protocol('WM_DELETE_WINDOW', lambda:tools.exitProg())

		#menubar:
		menubar = Menu(master)
		filemenu = Menu(menubar, tearoff = 0)
		filemenu.add_command(label="Open", command=tools.openLog)
		filemenu.add_command(label="Quit", command=tools.exitProg)
		menubar.add_cascade(label="File", menu = filemenu)

		runmenu = Menu(menubar, tearoff = 0)
		runmenu.add_command(label='Read file', command = tools.startUp)
		runmenu.add_command(label='Stop reading', command = tools.stop)
		runmenu.add_command(label='Clear', command = tools.clearTable)
		runmenu.add_command(label='Find log file', command = tools.findFile)
		menubar.add_cascade(label = "Tools", menu =runmenu)
		
		master.config(menu=menubar)

		#master frame:
		frame = Frame(master)
		frame.pack()

		w = []
		global label
		label=[None]*15
		_label=[None]*3
		#create labels
		for i in range(15):
			label[i]=_label[:]
		
		#Create a UNIQUE! stringVar at every index/subindex
		for i in range(15):
			for j in range(3):
				label[i][j] = StringVar()
		
		#setting header labels
		k=0
		for i in ['Amplitude', 'Phase', 'Time']:
			label[0][k].set(i)
			k+=1
		#create table
		for i in range(15):
			w.append(Frame(frame, borderwidth = 0))
			w[i].pack(side = TOP, fill = X)
			Label(w[i], text = i, width = 3, pady=0, bd=0).pack(side=LEFT)
			Label(w[i], textvariable = label[i][0], width = 10, pady=0, bd=0).pack(side=LEFT)
			Label(w[i], textvariable = label[i][1], width = 6, pady=0, bd=0).pack(side=LEFT)
			Label(w[i], textvariable = label[i][2], pady=0, bd=0, width = 9).pack(side=LEFT)


		
		statusbar = Frame(master)
		statusbar.pack(side = BOTTOM, fill = X)
		Label(statusbar, textvariable = tools.status, relief = SUNKEN).pack(fill = X)
		tools.findFile()
		master.mainloop()



class Tools:
	def __init__(self):
		self.status = StringVar()
		self.status.set('idle')
	def startUp(self):
		#initiate thread if file chosen
		if MainGui.filename:
			self.status.set('log name: '+os.path.splitext(os.path.basename(MainGui.filename))[0])
			t1 = FileReader()
			t1.setDaemon(1) #Makes thread Daemonic, i.e sys.exit w.o errors possible
			t1.start()
		else: 
			self.message('Pick a log file')

	def message(self, text):
		win = Toplevel()
		Label(win, text=text).pack()
		Button(win, text='OK', command = win.destroy).pack()

	def qmessage(self, label, text):
		import tkMessageBox
		x = tkMessageBox.askokcancel(label,text)
		# x=1 : ok, x=0 : Cancel
		return x


	def exitFileReader(self):
		#kills the thread of the FileReader if there is one
		if(MainGui.pid):
			os.popen('kill ' + str(MainGui.pid))
			#reset pid
			MainGui.pid = 0

	def exitProg(self):
		
		self.exitFileReader()
		master.destroy()
		sys.exit()

	def openLog(self):
		import tkFileDialog
		MainGui.filename = tkFileDialog.askopenfilename()


	def findFile(self):
		lf = LogFinder()
		lf.setDaemon(1)
		lf.start()

	def stop(self):
		#stops FileReader from reading, sets status to idle and clears the table
		self.exitFileReader()
		self.clearTable()
		self.status.set('idle')
			

	def clearTable(self):
		for i in range(1,15):
			for j in range(3):
				label[i][j].set('')


class FileReader(threading.Thread):
	def run(self):
		lr = LineReader()
		#try to open file, on fail, display error
		try:
			child = popen2.Popen3('tail -f '+ MainGui.filename)
			output = child.fromchild
			MainGui.pid = child.pid
		#in case of an error:
		except NameError:
			tools.stop()
			tools.message("Failed to run tail!")
		else: #if no error
		# child.poll() returns the exit status of child... -1 for running
			while child.poll() == -1:
				position = -1
				line = output.readline()
				l1 = lr.getData(line)			
				if l1: #if we got a list back, else None => l1 => false
					label[l1[0]][0].set(l1[2][0]) #amplitude
					label[l1[0]][1].set(l1[2][1]) #phase
					label[l1[0]][2].set(l1[3]) #date of measurement


			


class LogFinder(threading.Thread):
	def run(self):
		while 1:
			try:
				_child = popen2.Popen3('lognm')
			except NameError:
				tools.message('Could not run lognm')
				break
			else:
				logfile = _child.fromchild
				_filename = logfile.read().rstrip()
				logfile.close()
				filename = "%s%s%s" % ('/usr2/log/',_filename,'.log')
				if _filename=='': #no log, quit, remove """ to get question
					"""
					_answer = tools.qmessage("No log file found", "Quit?")
					if _answer:
						tools.exitProg()
					else:
						tools.exitFileReader()
						tools.status.set('idle')
						#if cancel, stop thread:
						break
					"""
					tools.exitProg()
				elif not filename==MainGui.filename: #change of logfile!
					#give MainGui the new filename
					MainGui.filename = filename
					#kill the Filereader thread if there is one:
					tools.exitFileReader()
					#start new thread with new filename
					tools.startUp()
				#re-check every 10s
				time.sleep(1)
		
class LineReader:

#constructor receives the line that is to be analyzed. 

	def __init__(self):
		#usbxy channels
		self.xchannel = 0
		self.ychannel = 0
		self.initiate = 1
		self.firstday = 0

	def getData(self, line):
		identification_table = ['usbx', 'usby', '/pcalports=', '/vsi4=,']
		for match in identification_table:
			listpos = 0
			position = line.find(match)
			if (position !=-1):
				position += len(match)
				if (match == '/pcalports=') or (match =='/vsi4=,'):
					_nfind = line[position:-1].split(',')
					xchannel = _nfind[0]
					ychannel = _nfind[1]
					self.setChannel([xchannel, ychannel])
				#check if xy channels are set
				elif (self.xchannel and self.ychannel): 
					data = 'something new'
					#check if xy channels are set
					if (match == 'usbx'):
						listpos = self.xchannel
						#record amp and phase
						_d1 = line[position+1:-1].split(' ')
						if len(_d1)<4:
							_d1 = ['*']*4
						data = [_d1[2], _d1[3]]
					if (match == 'usby'):
						listpos = self.ychannel
						#record amp and phase
						_d1 = line[position+1:-1].split(' ')
						if len(_d1)<4:
							_d1 = ['*']*4
						data = [_d1[2], _d1[3]]
					date = self.fixDate(line[0:20])
					return [int(listpos), match, data,date]
					#return listpos
			

	def setChannel(self, channel): 
		self.xchannel = channel[0]
		self.ychannel = channel[1]


	def fixDate(self,date):
		_date = date[9:-3]
		return _date

			

if __name__ == "__main__":
	startProg = MainGui()


			



